import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) throws Exception {
        // 我们已经能通过Class实例获取所有Field对象，同样的，可以通过Class实例获取所有Method信息。Class类提供了以下几个方法来获取Method：
        // Method getMethod(name, Class...)：获取某个public的Method（包括父类）
        // Method getDeclaredMethod(name, Class...)：获取当前类的某个Method（不包括父类）
        // Method[] getMethods()：获取所有public的Method（包括父类）
        // Method[] getDeclaredMethods()：获取当前类的所有Method（不包括父类）

        // 1、Method对象获取方法
        Class<?> stdClass = Student.class;
        // 获取public方法getScore，参数为String:
        System.out.println(stdClass.getMethod("getScore", String.class));
        // 获取继承的public方法getName，无参数:
        System.out.println(stdClass.getMethod("getName"));
        // 获取private方法getGrade，参数为int:
        System.out.println(stdClass.getDeclaredMethod("getGrade", int.class));

        // 2、Method对象调用方法
        // 通过Method对象，我们可以对任意对象调用对应的方法，使用Method.invoke(obj, Object...)方法：
        String s = "Hello world";
        // 获取String substring(int)方法，参数为int:
        Method m = String.class.getMethod("substring", int.class);
        // 在s对象上调用该方法并获取结果:
        String r = (String) m.invoke(s, 6);
        // 打印调用结果:
        System.out.println(r); // "world"

        // 3、Method对象调用static方法
        // 获取Integer.parseInt(String)方法，参数为String:
        Method m1 = Integer.class.getMethod("parseInt", String.class);
        // 调用该静态方法并获取结果:
        Integer n = (Integer) m1.invoke(null, "12345");
        // 打印调用结果:
        System.out.println(n);

        // 4、Method 调用非public方法
        Person p = new Person();
        Method m3 = p.getClass().getDeclaredMethod("printf_info");
        m3.setAccessible(true);
        m3.invoke(p);
        // 5、使用反射调用方法时，仍然遵循多态原则
        Method h = Person.class.getMethod("run");
        // 对Student实例调用hello方法:
        h.invoke(new Student());
    }

}

class Student extends Person {
    public int getScore(String type) {
        return 99;
    }

    private int getGrade(int year) {
        return 1;
    }
    @Override
    public void run(){
        System.out.println("Student is running");
    }
}

class Person {
    public String getName() {
        return "Person";
    }

    private void printf_info() {
        System.out.println("Some info");
    }
    public void run(){
        System.out.println("Person is running");
    }
}